AR(1)
π AR(1) Β· GNU Development Tools π
β¨ NAME β¨
ar - create, modify, and extract from archives π
π§ SYNOPSIS π§
ar [-X32_64] [-]p[mod] [--plugin name] [--target bfdname] [--output dirname] [--record-libdeps libdeps] [--thin] [relpos] [count] archive [member...]
π DESCRIPTION π
okay so the GNU ar program is the one that creates, modifies, and extracts from archives π¦ An archive is a single file that holds a whole collection of other files, stored in a way that lets you pull the original individual files back out. Those files are called members of the archive. It's giving organized folder energy, but make it a single file π
The original files' contents, mode (permissions), timestamp, owner, and group all get saved inside the archive, and they can be restored when you extract. Your files come back looking exactly like they went in β¨
GNU ar can keep archives whose members have names of any length π BUT, depending on how ar was configured on your system, there might be a limit on member-name length so it plays nicely with archive formats made by other tools π If there is a limit, it's often 15 characters (typical of formats related to a.out) or 16 characters (typical of formats related to coff). Lowkey annoying, but that's the deal.
ar is considered a binary utility π₯ because archives like this are mostly used as libraries that hold commonly needed subroutines. Libraries often depend on other libraries, so ar can also record a library's dependencies when you specify the --record-libdeps option π«Ά
ar builds an index of the symbols defined in relocatable object modules inside the archive when you specify the modifier s π Once it exists, that index gets updated in the archive whenever ar changes its contents (except for the q update operation, which we'll get to). An archive with an index speeds up linking to the library, and lets routines in the library call each other no matter where they sit in the archive. Iconic behaviour, honestly β¨
You can use nm -s or nm --print-armap to list this index table π If an archive doesn't have the table, another program called ranlib can be used to add just the table.
ar can also make a thin archive π¦ A thin archive holds a symbol index plus references to the original copies of the member files, instead of copies of the files themselves. This is super useful for building libraries for a local build tree, where the relocatable objects are expected to stick around anyway. Copying the contents of every object would only waste time and space, so thin archives just point at them instead π
An archive is either thin or normal, never both at the same time π ββοΈ Once an archive is created, its format can't be changed without deleting it first and then creating a new archive in its place. No take-backs, bestie.
Thin archives also get flattened π§ So if you add one thin archive to another thin archive, it doesn't nest inside it like it would with a normal archive. Instead, the elements of the first archive get added individually to the second archive. Clean and tidy, no cap.
The paths to the elements of a thin archive are stored relative to the archive itself πΈ
ar is designed to be compatible with two different facilities π You can control it with command-line options, like the different versions of ar on Unix systems. Or, if you specify the single command-line option -M, you can control it with a script supplied through standard input, like the MRI "librarian" program. Two ways to slay, pick your fave β¨
π OPTIONS π
okay, the options part is where the magic happens πͺ ar lets you mix the operation code p and the modifier flags mod in any order, as long as they're inside the first command-line argument.
If you want, you can even begin that first command-line argument with a dash π
The p keyletter is the operation to run. It can be any of the operations below, but you have to pick only one of them π
πΈ Operations πΈ
dβ Delete members from the archive ποΈ Name the members you want gone asmember.... If you don't specify any files to delete, the archive is left totally untouched.- If you add the
vmodifier,arlists each member as it gets deleted.
- If you add the
mβ Move members around inside an archive π¦- The order of members can make a real difference in how programs get linked against the library, especially if a symbol is defined in more than one member. So this one matters, bestie.
- If you don't use any modifiers with
m, any members you name in thememberarguments get moved to the end of the archive. If you want them somewhere specific instead, use thea,b, orimodifiers.
pβ Print the specified members of the archive to the standard output file π€- If you add the
vmodifier, the member name gets shown before its contents are copied to standard output. - If you don't name any member arguments, all the files in the archive get printed.
- If you add the
qβ Quick append πββοΈπ¨ Historically, this adds the filesmember...to the end of the archive, without checking for replacement.- The
a,b, andimodifiers don't affect this operation. New members always go at the end of the archive, no exceptions. - The
vmodifier makesarlist each file as it gets appended. - Since the whole point of this operation is speed, implementations of
arare allowed to skip updating the archive's symbol table if one exists. But too many systems just assume symbol tables are always up-to-date, so GNUarrebuilds the table even with a quick append. Safe choice, honestly. - > Note - GNU
artreats the commandqsas a synonym forr, meaning it replaces files that already exist in the archive and appends new ones at the end. Double check which one you meant, babe π
- The
rβ Insert the filesmember...into the archive, with replacement π This differs fromqbecause any previously existing members get deleted if their names match the ones being added.- If one of the files named in
member...doesn't exist,arshows an error message and leaves any existing members matching that name undisturbed. Not a total loss, phew π - By default, new members get added at the end of the file. But you can use one of the modifiers
a,b, orito place them relative to some existing member. - The
vmodifier used with this operation gives you a line of output for each file inserted, along with one of the lettersaorr.ameans the file was appended (no old member got deleted), andrmeans it replaced an old one.
- If one of the files named in
sβ Add an index to the archive, or update it if it already exists π₯ This one is a bit of a rule-breaker: there can normally only be one command letter, butscan be used as either a command or a modifier. Either way, it does the same thing β¨tβ Display a table listing the contents of the archive, or just the files named inmember...that are present in the archive π- Normally only the member name shows up. If you specify the
Omodifier, the corresponding offset of the member is displayed too. - To see the modes (permissions), timestamp, owner, group, and size, include the
vmodifier. - If you don't specify a member, every file in the archive gets listed.
- Quick heads-up: if there's more than one file with the same name (say,
fie) in an archive (say,b.a), thenar t b.a fieonly lists the first instance π To see all of them, you have to ask for a complete listing, which in our example would bear t b.a.
- Normally only the member name shows up. If you specify the
xβ Extract members (namedmember) from the archive π¦ You can use thevmodifier with this operation to makearlist each name as it's extracted.- If you don't specify a member, every file in the archive gets extracted.
- Files can't be extracted from a thin archive. There are also restrictions when extracting from archives created with
P: the paths must not be absolute, they may not contain.., and any subdirectories in the paths must already exist. If you want to dodge these restrictions, use the--outputoption to specify an output directory instead π«Ά
π Modifiers π
A bunch of modifiers (mod) can come right after the p keyletter to tweak how an operation behaves β¨
aβ Add new files after an existing member of the archive π If you usea, the name of an existing archive member has to be given as therelposargument, placed before the archive specification.bβ Add new files before an existing member of the archive π If you useb, the name of an existing archive member has to be given as therelposargument, placed before the archive specification. (Same asi.)cβ Create the archive π± The specified archive is always created if it didn't exist when you request an update. Butarissues a warning unless you say in advance that you expect to create it, which is what this modifier does.Dβ Operate in deterministic mode π§ When adding files and the archive index, this uses zero for UIDs, GIDs, and timestamps, and uses consistent file modes for all files. With this on, runningarwith identical options and identical input files gives identical output files every time, no matter the input files' owners, groups, file modes, or modification times. So reproducible, very clean.- If binutils was configured with
--enable-deterministic-archives, this mode is on by default. You can turn it off with theUmodifier, which is described below.
- If binutils was configured with
fβ Truncate names in the archive βοΈarnormally allows file names of any length. That can make archives that aren't compatible with the nativearprogram on some systems. If that's a concern for you, thefmodifier truncates file names when they go into the archive.iβ Insert new files before an existing member of the archive π If you usei, the name of an existing archive member has to be given as therelposargument, placed before the archive specification. (Same asb.)lβ Specify dependencies of this library π The dependencies must come immediately after this option character, must use the same syntax as the linker command line, and must be inside a single argument. So if you need multiple items, you have to quote them so they form one command-line argument. For example:
l "-L/usr/local/lib -lmydep1 -lmydep2"
Nβ Uses thecountparameter π’ This is for when there are multiple entries in the archive with the same name. It extracts or deletes instancecountof the given name from the archive.oβ Preserve the original dates of members when extracting them π°οΈ If you don't specify this modifier, files extracted from the archive get stamped with the time of extraction instead.Oβ Display member offsets inside the archive π Use this together with thetoperation.Pβ okay bestie, this one is all about full path names π£οΈPtells ar to use the whole path when it matches or stores names in the archive. Heads up though: archives made with full path names aren't POSIX compliant, so they might not play nice with anything except up-to-date GNU tools π. If you modify one with GNU ar withoutP, the full path names get stripped, unless it's a thin archive.Pis also useful when you add files to a thin archive, becauserwithoutPignores the path when picking which element to replace. Like, watch this:
ar rcST archive.a subdir/file1 subdir/file2 file1
This will replace the first "subdir/file1" with "file1" from the current directory π. Add P and that replacement gets prevented π
ββοΈ.
sβ writes an object-file index into the archive, or updates an existing one, even if nothing else changed β¨. You can use it with any operation or all on its own. Runningar son an archive is the same as runningranlibon it π§.Sβ no archive symbol table gets generated π«Ά. This can speed up building a big library in several steps. The catch is that the resulting archive can't be used with the linker π«. To get a symbol table, leave offSon the lastarrun, or just runranlibon the archive.Tβ deprecated alias for--thinπ. Don't use it, bestie, because in lots of ar implementationsTmeans something totally different, as defined by the X/Open System Interface.uβ okay so normallyar r...inserts every file you list π . Withu, only the files that are newer than the existing members with the same names get inserted.uis only allowed with ther(replace) operation. Andquis a big no, because checking the timestamps would cancel out the speed boost fromqπ.
Note: if an archive was created in a deterministic way, e.g. with theDmodifier, then replacement will always happen anduwon't do anything π.
Uβ not deterministic mode πΈ. This is the inverse ofD: added files and the archive index get their actual UID, GID, timestamp, and file mode values. This is the default unless binutils was configured with--enable-deterministic-archives.vβ verbose mode, the main character version of an operation π¦. Lots of operations will show extra info, like the filenames they processed, when you addv.Vβ shows the version number of ar π₯.
The ar program also has some command-line options that aren't modifiers or actions, but they still change how it behaves in specific ways π:
--helpβ shows the list of command-line options ar supports, then exits π.--versionβ shows ar's version information, then exits π.-X32_64β ar ignores an initial option spelled-X32_64, for AIX compatibility π. The behaviour this option produces is already the default for GNU ar. ar doesn't support any of the other-Xoptions, and in particular it doesn't support-X32, which is the default for AIX ar π€.--plugin nameβ this optional switch makes ar load the plugin calledname, which adds support for more file formats, including object files with link-time optimization information π§ββοΈ. This option is only available if the toolchain was built with plugin support enabled. If you don't give--pluginbut plugin support is enabled, ar goes through the files in${libdir}/bfd-pluginsin alphabetic order, and the first plugin that claims the object in question gets used π.
Please note, this plugin search directory is not the one used by ld's -plugin option π. To make ar use the linker plugin, it has to be copied into the ${libdir}/bfd-plugins directory. For GCC based compilations the linker plugin is called liblto_plugin.so.0.0.0, and for Clang based compilations it's called LLVMgold.so π. The GCC plugin is always backwards compatible with earlier versions, so you can just copy the newest one β¨.
--target targetβ the optional switch--target bfdnamesays the archive members are in an object code format that's different from your system's default format π. See--output dirnameβ lets you pick a path to a directory where archive members get extracted π. If you don't specify this, the current directory is used.
Note: even though this option implies an x extraction operation, that option still has to be included on the command line π.
--record-libdeps libdepsβ identical to thelmodifier, just in long form π.--thinβ makes the specified archive a thin archive π¦. If it already exists and is a regular archive, the existing members must be in the same directory as the archive.@fileβ reads command-line options from file π«§. The options it reads get inserted in place of the original@fileoption. If the file doesn't exist or can't be read, the option gets treated literally and isn't removed.
Options in the file are separated by whitespace. If you want a whitespace character inside an option, wrap the entire option in single or double quotes. Any character (including a backslash) can be included by putting a backslash in front of it. The file can even contain more @file options of its own, and those get processed recursively π.
β¨ SEE ALSO β¨
nm(1), ranlib(1), and the Info entries for binutils π.
π©· COPYRIGHT π©·
Copyright (c) 1991-2025 Free Software Foundation, Inc. π
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License" π.
That's the whole AR(1) tea, bestie π«Ά binutils 2.45, dated December 3rd, 2025, and this page is officially iconic πβ¨ periodt π
π¦ where this page comes from
- ubuntu questing: binutils-common 2.45-7ubuntu1.2
- ubuntu questing: binutils-x86-64-linux-gnu 2.45-7ubuntu1.2
- π girlified by anthropic/claude-haiku-5.5 on : a language model's rewrite of the original, under its terms