123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- use std::fs;
- use std::path::PathBuf;
- use std::process::Command;
- use std::result::Result;
- use structopt::StructOpt;
- use ar::Archive;
- use std::fs::File;
- use std::io;
- #[derive(Debug, StructOpt)]
- #[structopt(name = "Localize", about = "Localize a static library into a single object archive")]
- struct LocalizeArgs
- {
- /// list of file to merge
- #[structopt(name = "FILE LIST", short = "i", long = "inputs")]
- input_files: Vec<PathBuf>,
- /// filename of the final library archive
- #[structopt(name = "OUT FILE", short = "o", long = "output")]
- output_file: PathBuf,
- }
- fn extract(input: PathBuf, output_directory: PathBuf)
- -> Result<Vec<PathBuf>, ()>
- {
- println!("Extracting {:?} into {:?}", input, output_directory);
- let input_file = File::open(input)
- .map_err(|_| ())?;
- let mut file_list : Vec<PathBuf> = vec![];
- let mut archive = Archive::new(input_file);
- while let Some(entry_result) = archive.next_entry()
- {
- let mut entry = entry_result.unwrap();
- let identifier = std::str::from_utf8(
- entry.header().identifier()).unwrap();
- let mut output_filename = output_directory.clone();
- output_filename.push(identifier);
- println!(" - {:?}", output_filename);
- let mut file = File::create(&output_filename)
- .unwrap();
- file_list.push(output_filename);
- io::copy(&mut entry, &mut file)
- .map_err(|_| ())?;
- }
- Ok(file_list)
- }
- fn link_partial(inputs: Vec<PathBuf>, output: &PathBuf)
- -> Result<(), ()>
- {
- Command::new("ld")
- // Enable partial linking
- .arg("-r")
- .arg("-o")
- .arg(&output)
- .args(&inputs)
- .output()
- .unwrap();
- Ok(())
- }
- fn localize_hidden(input: &PathBuf)
- {
- /* On MacOSX, check
- * -[un|re]exported_symbols_list
- * -[un]exported_symbol
- * See
- * https://developer.apple.com/library/archive/technotes/tn2185/_index.html#//apple_ref/doc/uid/DTS10004200-CH1-SUBSECTION5
- * */
- Command::new("objcopy")
- .arg("--localize-hidden")
- .arg("--strip-unneeded")
- .arg(&input)
- .output()
- .unwrap();
- }
- fn link(args: LocalizeArgs)
- {
- let output_dir = "./output_dir/";
- // TODO: the output directory might already exist
- fs::create_dir(output_dir)
- .expect("Cannot create output directory");
- let input = fs::canonicalize(args.input_files[0].clone())
- .expect("Input path is invalid");
- extract(input, PathBuf::from(&output_dir))
- .expect("Cannot extract library archive");
- println!("Archive objects successfully extracted");
- // TODO list files
- let files = vec![
- fs::canonicalize("./output_dir/lib1.o").unwrap(),
- fs::canonicalize("./output_dir/lib2.o").unwrap() ];
- let output = args.output_file; //fs::canonicalize(args.output_file).unwrap();
- link_partial(files, &output);
- localize_hidden(&output);
- }
- fn main() {
- let opt = LocalizeArgs::from_args();
- println!("{:?}", opt);
- link(opt);
- }
|