Git ignore file for C projects - c

I've just started to learn C (using Thinking In C) and I'm wondering about what files I should be ignoring in a C project's git repository.
No suggestion can be too obvious -- I'm a total noob. Thanks!

I guess there will be a few generated files that you don't wan't to be sticking in your repo (assuming your build output dir is in your git heirachy):
object files (.o, o.obj)
libraries (.lib)
DLLs, shared objects (.so, .dll)
Executables (.exe, a.out ?)
GIT ignore files are something I tend to do iteratively. "Hey, I don't need those things in my repo" ...
Edit: re dmckee's comment
Yep, you definately want to be ignoring swap files, temp files etc. I have the following as a baseline for my .gitignore:
*.swp
.~
thumbs.db

You can also setup your build to happen in a subdirectory say build and then you can ignore the whole thing inside .gitignore
build/
And you're done.

I use this in my .gitignore
But I am building for micro-controllers, so I don't know if it helps you much.
The easiest way to know, is just do a make clean, then add all your files, then do a make all and see what extra stuff appears.
#Some of these are related to eclipse. So i keep them out of my repo
.cproject
.dep/
.project
.settings/
#files being edited
*~
# make and build files
*.lst
*.o
*.eep
*.lss
*.map
*.sym
# I keep these, since I prefer having the reference of the final build
# *.elf
# *.hex

Github's .gitignore file templates cover most of the common files for projects in a variety of languages.
The C .gitignore template looks like this:
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

Using a *nix system and a Makefile, you could add each generated file to .gitignore.
As an example I use the following when creating an executable from a single source (Example for a C executable generation):
%: %.c
gcc -o $# $<
grep '^$#$$' .gitignore > /dev/null || echo '$#' >> .gitignore
The following line can be added to other recipes to add target $# to .gitignore file:
grep '^$#$$' .gitignore > /dev/null || echo '$#' >> .gitignore
Explanation:
grep '^$#$$' .gitignore : searches for the target in .gitignore
^ indicates start of line
$$ is a single $ (but Makefile needs $$ to work) and indicates the end of the line
'^$#$$' represents the target name
|| : executes the next command only if the left hand one failed
so only if grep ... does not find the target name in .gitignore, echo ... is executed
echo '$#' >> .gitignore: adds the target name to .gitignore
Eventually, you will add to clean and rebuild everything to make sure all files are correctly ignored

Related

Error while executing cross-compiled program for openwrt

I'm trying to export a software to openwrt and i'm able to generate the ipk but the compiled file always gives me this error
-ash: scanReportProbe: not found
I've tried everything but i'm not able to make it work.
To be complete this is what i have done to prepare the environment:
git clone git://github.com/openwrt/openwrt.git
cd openwrt
./scripts/feeds update -a
./scripts/feeds install -a
make defconfig
make prereq
make menuconfig
[here i selected the package with the M and saved the configuration]
make tools/install
make toolchain/install
make package/scanReport_probe/compile
I have no idea of to fix this error so i need some hint of solution.
I don't think that the error is in the code but in casse is needed this is my program:
file structure
scanReport_probe
├── LICENSE
├── Makefile
├── README.md
└── src
├── data
│ └── THIS IS FOR DATA FILES.txt
├── runScript
│ └── scanReportProbe
├── scanReport_probe
│ ├── a.c
│ └── makefile
└── scanReport_probe.conf
makefile for openwrt
include $(TOPDIR)/rules.mk
# name of package
# version number of the sources you're using
# how many times you've released a package based on the above version number
PKG_NAME:=scanReport_probe
PKG_VERSION:=1.0
PKG_RELEASE:=1
PKG_LICENSE:=MIT
# sources will be unpacked into this directory (you shouldn't need to change this)
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
#needed
include $(INCLUDE_DIR)/package.mk
# Metadata; information about what the package is for the ipkg listings
# to keep things simple, a number of fields have been left at their defaults
# and are not shown here.
define Package/scanReport_probe
SECTION:=utils
CATEGORY:=Utilities
TITLE:=scanReport_probe
URL:=https://github.com/luigiDB/scan-report_probe
TITLE:=Scan in monitor mode probe over wifi channel with periodic report to a server through http post.
MAINTAINER:=Please refer to github repository page
endef
define Package/scanReport_probe/description
This is the best tool ever.
Scan probe over wifi and at regualar interval send results via http post.
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
CONFIGURE_VARS+= \
CC="$(TOOLCHAIN_DIR)/bin/$(TARGET_CC)"
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR)/scanReport_probe $(TARGET_CONFIGURE_OPTS)
endef
# We'll use the OpenWrt defaults to configure and compile the package. Otherwise we'd need to define
# Build/Configure - commands to invoke a configure (or similar) script
# Build/Compile - commands used to run make or otherwise build the source
define Package/scanReport_probe/install
# Now that we have the source compiled (magic huh?) we need to copy files out of the source
# directory and into our ipkg file. These are shell commands, so make sure you start the lines
# with a TAB. $(1) here represents the root filesystem on the router.
# INSTALL_DIR, INSTALL_BIN, INSTALL_DATA are used for creating a directory, copying an executable,
# or a data file. +x is set on the target file for INSTALL_BIN, independent of it's mode on the host.
# make a directory for the config
$(INSTALL_DIR) $(1)/etc/scanReport_probe/
# copy the config
$(INSTALL_CONF) $(PKG_BUILD_DIR)/scanReport_probe.conf $(1)/etc/scanReport_probe
# make a directory for some random data files required by scanReport_probe
$(INSTALL_DIR) $(1)/usr/share/scanReport_probe
# copy the data files
$(INSTALL_DATA) $(PKG_BUILD_DIR)/data/* $(1)/usr/share/scanReport_probe
#make directory bin
$(INSTALL_DIR) $(1)/bin
# copy the binary
$(INSTALL_BIN) $(PKG_BUILD_DIR)/scanReport_probe/scanReportProbe $(1)/bin
#make the directory init.d in case isn't present
$(INSTALL_DIR) $(1)/etc/init.d
#copy script to init.d
$(INSTALL_BIN) $(PKG_BUILD_DIR)/runScript/scanReportProbe $(1)/etc/init.d
endef
#runned post installation call the enable on the service
define Package/scanReport_probe/postinst
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
echo "Enabling rc.d symlink for scanReportProbe"
/etc/init.d/scanReportProbe enable
fi
exit 0
endef
#runned pre uninstallation call the disable on the service
define Package/scanReport_probe/prerm
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
echo "Removing rc.d symlink for scanReportProbe"
/etc/init.d/scanReportProbe disable
fi
exit 0
endef
$(eval $(call BuildPackage,scanReport_probe))
a.c
#include <stdio.h>
int main(void)
{
printf("Hello World\n");
return 0;
}
makefile for c program
PROFILE = -O2 -s
CFLAGS = $(PROFILE)
LDFLAGS =
all: main
# build it
main: a.o
$(CC) $(LDFLAGS) a.o -o scanReportProbe
a.o: a.c
$(CC) $(CFLAGS) -c a.c
# clean it
clean:
rm *.o a
For -ash, IIRC, ash is a [boot] shell. It is saying that it can't find a particular command.
So, it may be one of:
(1) In your rc script section, you're doing /etc/init.d/scanReportProbe enable but the package you're building uses scanReport_probe. So, you may need to add or remove an _ here or there and/or some other renames so things match up.
(2) If the file structure you gave is the final one, I'm not sure the script is in the right directory.
(3) Are the permissions for the script correct (i.e. has execute)?

Unable to make libtool incorporate yasm-created object files

I'm trying to get libtool and yasm to work together.
yasm creates the correct .o files from my .asm sources, but I can't figure out how to get libtool to build the associated .lo and .dep files.
It wants to build the shared library, incorporating the .o files.
libtool generated files typically use the following layout: The .lo file in a build directory consisting of location metadata; the static object .o files in the build directory; and the PIC / shared .o objects in the build/.libs directory.
You can use the libtool compile mode. I'm not familiar with yasm, so you'll have to fill in the switches. It will run the yasm build twice, once with -DPIC (and maybe other shared object options).
libtool --tag=CC --mode=compile yasm <options> src.asm
If using automake, this may require an explicit rule for the .asm files:
.asm.lo:
$(LIBTOOL) --tag=CC --mode=compile \
yasm <options> $<
Keep in mind that those are TABs in Makefiles, not (8) space characters!
You might also need to add: .SUFFIXES: .asm .lo prior to this. I use the variable $(LIBTOOL), because some platforms (OSX for example) need to install it as glibtool, and it's what Makefile.indoes.
The generated src.lo, src.o, .libs/src.o should be respected by make clean for example.
For your library libfoo, you will need to let automake know about these sources with: EXTRA_libfoo_la_SOURCES = src.asm, and obj deps with libfoo_la_LIBADD = src.lo. It might be even be worthwhile adding to dependencies: libfoo_la_DEPENDENCIES = src.lo.
Though I don't see why just putting src.asm in libfoo_la_SOURCES wouldn't be sufficient.
This works (although I never did figure out how to get libtool to create the .lo file in the target directory, or to create the target directory's .libs directory).
The Makefile rule:
# Rule to build object files from asm files.
#
# XXX
# Libtool creates the .lo file in the directory where make is run. Move the file
# into place explicitly; I'm sure this is wrong, but have no idea how to fix it.
# Additionally, in a parallel make, the .libs file may not yet be created, check
# as necessary, but ignore errors.
.asm.lo:
-d=`dirname $#`; test $d/.libs || mkdir $d/.libs
$(LIBTOOL) --tag=CC --mode=compile sh $(srcdir)/dist/yasm.sh $< $#
rm -f $#
mv `basename $#` $#
A support shell script to do the yasm call:
#! /bin/sh
# Libtool support for yasm files, expect the first argument to be a path to
# the source file and the second argument to be a path to libtool's .lo file.
# Use the second argument plus libtool's -o argument to set the real target
# file name.
source=$1
target=`dirname $2`
while test $# -gt 0
do
case $1 in
-o)
target="$target/$2"
shift; shift;;
*)
shift;;
esac
done
yasm -f x64 -f elf64 -X gnu -g dwarf2 -D LINUX -o $target $source

subdir-objects option for automake doesn't work

After reading the autotools mythbuster, I have tried to write a little example of the non recursive makefile with the use of subdir-objects in order to have my binary in the directory of my source files.
Here is the the organization of my little test:
/
autogen.sh
configure.ac
Makefile.am
src/
main.c
The autogen.sh :
#!/bin/sh
echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS || exit 1
echo "Running autoheader..." ; autoheader || exit 1
echo "Running autoconf..." ; autoconf || exit 1
echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1
./configure "$#"
The configure.ac :
AC_PREREQ([2.69])
AC_INIT([test], [0.0.1], [devel#hell.org])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
AM_INIT_AUTOMAKE([1.14 foreign subdir-objects])
AM_MAINTAINER_MODE([enable])
AC_OUTPUT(Makefile)
The Makefile.am :
MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.h.in configure depcomp install-sh missing compile
bin_PROGRAMS=toto
toto_SOURCES=src/main.c
I compile everything with :
./autogen.sh
make
I thought that the binary toto would have been created in the src directory with the option subdir-objects but it seems that this option have no effect and the toto binary is always generated in the root directory.
I have also tried to pass this option in the Makefile.am with AUTOMAKE_OPTIONS = subdir-objects but wihtout success.
That's not what the subdir-objects option does. It puts intermediate build results, especially *.o object files, in the same directory as the sources from which they are built. In particular, you should find main.o there instead of in the top directory.
The final build result, on the other hand, must be what and where you specify in your Automake file. If you want toto to go in the src/ directory too, then use this Makefile.am:
MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.h.in configure depcomp install-sh missing compile
bin_PROGRAMS=src/toto
src_toto_SOURCES=src/main.c

Confused about Makefile (C/unix)

http://puu.sh/7OiDL.png
Ok so what does export: StackImplementation.o do? Like where does it export that to?
Also, what is gcc -l doing? I googled it and it says "gcc -l links with a library file". What's linking to the library file?
Lastly, what does "substitute a print command of your choice for lpr below" mean? What's lpr do? and what's clean: rm -f *.o?
The export is the name of a phony target. You can say
% make export
And make will build the its dependencies. There is no action specifying how to convert the dependencies into a file called export, and in the absence of an implicit rule, the make will stop after building the dependencies.
The -I to gcc is adding a path to search for include files. You are confusing it with the -l option which specifies the name of a library to link (a pre-built collection of object files from which unresolved symbols can be satisfied).
The lpr command sends a file to the default line printer. Again, print is a phony target; doing
% make print
sends the source file to the printer.
Most makefiles include a clean rule to delete generated files. It is necessary when the dependencies are not properly specified, and a change to a source file does not cause the target to be built. The rm command is short for remove; it deletes files. If you do
% make clean
it will force-delete all files that end with .o.
Most of these targets are phony, and will not work correctly if there happen to be files with those names that are newer than their dependencies (if any). Most makes allow you to specify which targets are phony by listing them as dependencies of a super phony .PHONY target. Make will then ignore the filesystem, and will always apply the rules.
export:
this is a target named "export" and is the first target in the makefile so it will get called by default if no target is specified on the command line. Not clear to me why it is called "export" but that's the name somebody chose for it
export: StackImplementation.o
this says that export depends on StackImplementation.o so it will invoke the target StackImplementation.o when export is invoked
StackImplementation.o: StackImplementation.c ...
StackImplementaiton.o depends on the source file StackImplementation.c and the include files listed. This will run gcc which has the flag -I../Include which tells gcc to include .h files in adjacent directory "Include"
# substitute...
this is a comment indicating to change the print command lpr to some other print command if you want to
clean:
this is a common target that will delete object files with the -f option, forcing remove even if write permission is not set
1) lpr submits files for printing. Files named on the command line are sent to the named printer
(or the default destination if no destination is specified). If no files are listed on the com‐
mand-line, lpr reads the print file from the standard input.
for more information about "lpr " use user manual of linux.
2)gcc -l link external library to your program if any dependency .
example::
gcc hello.c -o hello -lpthread -ldrm -ldrm_omap
in Make file::
clean:
rm -rf *.o
here clean is a rule of make and when we call make clean then it will invoke rm -rf *.o to remove all object files.

Meaning of pattern in rm command

I found this rm command in a Makefile.
rm -f $(ODIR)/*.o *~ $(PROG) $(INCDIR)/*~
What is the meaning of *~?
*~ is not special. It matches files that end with the ~ character (often editor backup files).
emacs is one program which leaves files ending with ~ around as backup files. So the creator of the makefile was probably an emacs user who wanted this target (perhaps clean?) to clean up .o files and executables and emacs droppings.
It means all files with a ~ at the end, no matter what the other letters of the filename are. These are usually temporary files.

Resources