How to Build Git with Static Linking

compile or download a static version of git

I needed a quick solution and therefore I simply used darcs.

The static binaries of darcs are about 26mb big, they are very portable and are excellent for older systems. I got quickly used to the darcs commands, although I first though that this would take more time.

SmartGit could also help, but I think the whole client it is not open source. Further, I needed a console client for a bash script.

Undefined Reference at Linking in Static Git Build

I finally discovered a different guide, which advised running a slightly different .configure command. What ended up working for me was this guide, with the exception of running

$ ./configure --prefix=/home/myuser/git-static CFLAGS="${CFLAGS} -static" NO_OPENSSL=1 NO_CURL=1

in step 2.

Statically build and linking with CMake

For libraries, like CURL, that have first-class CMake package support, you should use it. Here is how I linked to CURL statically.

First, we download and build CURL:

$ git clone git@github.com:curl/curl.git
$ cmake -G Ninja -S curl/ -B _build/curl -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=NO
$ cmake --build _build/curl
$ cmake --install _build/curl --prefix _local

After this, we can write the correct CMakeLists.txt, which only links to imported targets. Notice that this build uses no variables.

cmake_minimum_required(VERSION 3.23)
project(test)

find_package(CURL REQUIRED)

add_executable(static-test main.cpp)
target_link_libraries(static-test PRIVATE CURL::libcurl)

And now we can build this, pointing CMake to our freshly built CURL package, via CMAKE_PREFIX_PATH:

$ cmake -G Ninja -S . -B _build/test -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$PWD/_local
...
-- Found CURL: /path/to/_local/lib/cmake/CURL/CURLConfig.cmake (found version "7.85.0-DEV")
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/_build/test

and now we can run the build and see that all of the required libraries are there:

$ cmake --build _build/test --verbose
[1/2] /usr/bin/c++ -DCURL_STATICLIB -isystem /path/to/_local/include -O3 -DNDEBUG -MD -MT CMakeFiles/static-test.dir/main.cpp.o -MF CMakeFiles/static-test.dir/main.cpp.o.d -o CMakeFiles/static-test.dir/main.cpp.o -c /usr/local/google/home/reinking/test/main.cpp
[2/3] : && /usr/bin/c++ -O3 -DNDEBUG CMakeFiles/static-test.dir/main.cpp.o -o static-test ../../_local/lib/libcurl.a -ldl -lpthread /usr/lib/x86_64-linux-gnu/libssl.so /usr/lib/x86_64-linux-gnu/libcrypto.so /usr/lib/x86_64-linux-gnu/libz.so && :

As you can see, curl and its transitive dependencies, dl, pthreads, openssl, libcrypto, and libz, all appear correctly on the link line.

Unable to link the output (static library) of an external git CMake project to a CMake project

It looks like you're building octal OK, but aren't providing proper paths to its sources (for bulletframe to be able to #include it) nor to its compiled library.

Fixing the includes issue is simple; just add the path to the imported library's INTERFACE_INCLUDE_DIRECTORIES property. However, fixing the library's path is a little trickier.

With MSVC, the full path to the octal lib will be

${OCTAL_SOURCE_DIR}/lib/<build type>/octal.lib

where <build type> is "Debug", "Release", etc. However, with other compilers, the path will be

${OCTAL_SOURCE_DIR}/lib/liboctal.a

To get round this, I'd do something like:

add_library(octal STATIC IMPORTED)
if(MSVC)
set_target_properties(octal PROPERTIES
IMPORTED_LOCATION_DEBUG "${OCTAL_SOURCE_DIR}/lib/Debug/octal.lib"
IMPORTED_LOCATION_RELEASE "${OCTAL_SOURCE_DIR}/lib/Release/octal.lib"
INTERFACE_INCLUDE_DIRECTORIES "${OCTAL_SOURCE_DIR}/src")
else()
set_target_properties(octal PROPERTIES
IMPORTED_LOCATION "${OCTAL_SOURCE_DIR}/lib/liboctal.a"
INTERFACE_INCLUDE_DIRECTORIES "${OCTAL_SOURCE_DIR}/src")
endif()

How to build a C program using a custom version of glibc and static linking?

Following a couple of suggestions from the glibc help mailing list (libc-help@sourceware.org), I have a solution. It turns out that this task is a bit tricky because you have to tell the linker to omit everything it would normally include automatically (and silently), and then include back everything that it needs, including a bunch of start and end files. Some of the start and end files come from libc and some come from gcc, so the make rule is a bit complicated. Below is a general sample makefile to illustrate the approach. I will assume that you are building a program called prog from a source file called prog.c and that you have installed your custom glibc in directory /home/my_acct/glibc_install.

TARGET = prog
OBJ = $(TARGET).o
SRC = $(TARGET).c
CC = gcc
CFLAGS = -g
LDFLAGS = -nostdlib -nostartfiles -static
GLIBCDIR = /home/my_acct/glibc_install/lib
STARTFILES = $(GLIBCDIR)/crt1.o $(GLIBCDIR)/crti.o `gcc --print-file-name=crtbegin.o`
ENDFILES = `gcc --print-file-name=crtend.o` $(GLIBCDIR)/crtn.o
LIBGROUP = -Wl,--start-group $(GLIBCDIR)/libc.a -lgcc -lgcc_eh -Wl,--end-group

$(TARGET): $(OBJ)
$(CC) $(LDFLAGS) -o $@ $(STARTFILES) $^ $(LIBGROUP) $(ENDFILES)

$(OBJ): $(SRC)
$(CC) $(CFLAGS) -c $^

clean:
rm -f *.o *.~ $(TARGET)


Related Topics



Leave a reply



Submit