Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Desarrollo En Linux...

Iniciado por TheAzazel, 06 de Febrero de 2005, 08:36:29 PM

« anterior - próximo »

TheAzazel

 Siguiendo con la tradicion...... os lanzo una pregunta a ver si alguien me puede echar un cable :)

resulta que bueno, ya me instale el suse 9.2 pro y luego el kdevelop con todas las utilidades de desarrollo(gcc,automake, etc.) ya que de "serie" el pro no lo tiene... tendria q ser el enterprise pero vale pelas je.

He compilado sin problemas todas las librerias de CRM32Pro (normal, son multiplataforma jeje) y CRM32Pro con unos pequeños ajustes en la cabecera para separar win32 de linux tambien compila pero tengo q hacer un testeo de todo.

El rollo esta en que...tengo q meterme a fondo con los ficheritos makefile... y la question es...conoceis algun buen tuto q me los explique? o algun libro que cubra esto y los demas relacionado?? reconozco q los makefile y cia ... siempre los habia dejado a su bola pero ahora q tengo q ponerme con ellos... dan dolor de cabeza.... y necesito comermelos :).

Cualquier ayuda es buena :), un saludo

Zaelsius

 http://www.dlsi.ua.es/asignaturas/hp/

Descarga los PDF's en la sección "Material de trabajo". Olvida el autoconf y automake hasta que no domines completamente los makefiles "a mano" :rolleyes:, y apréndelos bien porque son el pan nuestro de cada dia en cuanto te sales un poco de los entornos visuales más conocidos.

TheAzazel

 Ya.... en epoca msdos recuerdo aun el watcom y el edit o luego algun editor(q ya ni recuerdo el nombre) y tal... pero era mas manual... luego me pase a visualC y me volvi vago....
aunq.... dicho sea de paso, podrian hacer algo parecido a visual C jijij, para controlar proyectos y tal es facilisimo(o es q ya stoy acostumbrado :) ).
Pos gracias, mañana me los imprimo en el curro y me los studiooo  :D  

samsaga2

 Se sale un poco del tema pero hace poco navegando me encontre esto por ahi, iCompile:

http://ice.sourceforge.net/

Programa que promete que podras compilar sin tener que configurar Makefiles ni nada por el estilo.

Me gusto bastante la idea pero no la forma que usan para detectar con que librarias tiene que enlazar asi que me puse manos a la obra y me he estado currando un programa en perl que haga lo mismo.

El programa detectara automaticamente que las librerias y directorios de includes que tiene que usar. Ahora lo tengo bastante usable, solo me queda añadir dependencias. No lo tengo aqui pero si alguien me lo pide se lo puedo pasar.

DraKKaR

 Hace un tiempo, un programador estaba currandose un clon del Visual Studio de Microsoft. Se llamaba MinGW Studio. Yo me lo bajé y erabastante parecido (en apariencia y forma de uso). Es una lástima, porque parece que ha dejado de trabajarse en este IDE. Podeis ver sus restos googleado con "parinya studio".

Samsaga, tu herramienta suena interesante. Ánimo que puede ser una buena opción.

TheAzazel

 Estoy mirando el iCompile y parece que esta bien, he de mirarlo mas a fondo porque necesito algunas funciones extras....
el programilla esa en perl..... lo podrias colgar por aki? a mi eso de que utilice las variables de entorno tampoco mola muxo...


sés

 ¿Qué tal este? -> Ultimate++

Le he echado un vistazo por encima y promete bastante.
Soy indeciso... ¿o no?

samsaga2

Cita de: "TheAzazel"Estoy mirando el iCompile y parece que esta bien, he de mirarlo mas a fondo porque necesito algunas funciones extras....
el programilla esa en perl..... lo podrias colgar por aki? a mi eso de que utilice las variables de entorno tampoco mola muxo...
El script que estoy montando en perl coge automaticamente (automagicamente como dirian los americanos) cualquier include o libreria que tengas instalada en el sistema (si no esta instalada en los directorios tipicos de linux puedes añadirlo a la linia de comandos).

Esta tarde cuando llegue a casa hago un copy&paste en el foro. Ahora mismo es un programa solo de prueba pero si me sale bien continuare su desarrollo.

Que otras funciones extras necesitas?

samsaga2

 Mini post :-P

Usarlo es facil te metes en el directorio donde estan los codigos fuentes y lo ejecutas, si todo va bien el resultado sera un bonito ejecutable.  Puedes usar --dynamic-lib para crear librerias dinamicas, --static-lib para crearlas estaticas. Hay algunas opciones mas, miralas con --help.

Se me olvidaba, ten en cuanta que la primera vez que se ejecuta el programa en un directorio crea una cache con los includes y librerias del sistema, si se modifica alguna o instalas una nueva tendras que volver a crear la cache (opciones -f y -i).

Espero que le sirva de ayuda a alguien.

PD: Al hacer copy&paste algunos tabuladores no me los ha puesto bien.


#!/usr/bin/env perl

#
# GPL Copyright 2005 Victor Marzo
# All rights reserved
#
# samsaga2@gmail.com
#

use strict;
use Getopt::Long;
use File::Find;
use File::Basename;

### Reset language ###
$ENV{"LANG"} = "";

### Read IBuilder config ###
my $builder_file = "";
if(-f "ibuilder.config") {
$builder_file = "ibuilder.config";
}

my %options = (
APPNAME => "Unnamed",
APPVERSION => "0.0",
EXECUTABLE => "a.out",
INCPATHS => "/usr/include:/usr/local/include:/usr/X11R6/include:.",
LIBPATHS => "/usr/lib:/usr/local/lib:/usr/X11R6/lib:.",
SONAMEVERSION => "0",
STATICLIB => 0,
DYNAMICLIB => 0,
LIBS => "",
DEFINES => "",
DEBUG => 0,
NOLINK => 0,
RUN => 0,
CACHINGINCS => 0,
CACHINGLIBS => 0
);

my %files;
my @cpp_objfiles;
my %libfunctions;
my @incfiles;

#
# Adivine configuration
#
sub autoconf {
### Search app name, version and executable name ###
my $name = basename($ENV{"PWD"});
my $version = "0.0";

if($name =~ /-/) {
 $name =~ /^(.*)-(.*)/;
 $name = $1;
 $version = $2;
}

$options{"APPNAME"} = $name;
$options{"APPVERSION"} = $version;
$options{"EXECUTABLE"} = lc $name;

if($version =~ /\./) {
 my @version = split(/\./, $version);
 $options{"SONAME"} = $version[0];
} else {
 $options{"SONAME"} = $version;
}
}

#
# Show help
#
sub show_help() {
print "
ibuilder [options]:
-f file.config  Use file.config file for builder config
-h   Show help
-r,--run  Run executable
-l   Skip linking phase
-f   Force caching libraries
-i   Force caching includes
--clean   Clean trash files
-D def1:def2:... Define names
--debug   Enable debug
--dynamic-lib  Create dynamic link
--static-lib  Create a static lib
-I includes:includes Add includes path
";
}

#
# Clean files
#
sub clean_files() {
### Clean cached files ###
`rm -rf .ibuilder`;

### Clean obj files ###
find(\&search_clean_find, ".");

sub search_clean_find {
 my $name = $File::Find::name;
 if (!-d $name && $name =~ /\.o$/) {
  `rm -f "$name"`;
 }
}

### Clean executable ###
`rm -f "$options{EXECUTABLE}"`;
}

#
# Read command-line arguments
#
sub parse_args() {
my $help = 0;
my $clean = 0;
my $includes = "";

GetOptions(
 "f=s" => \$builder_file,
 "file=s" => \$builder_file,
 "r" => \$options{'RUN'},
 "run" => \$options{'RUN'},
 "l" => \$options{'NOLINK'},
 "f" => \$options{'CACHINGLIBS'},
 "i" => \$options{'CACHINGINCS'},
 "D" => \$options{'DEFINES'},
 "debug" => \$options{'DEBUG'},
 "static-lib" => \$options{'STATICLIB'},
 "dynamic-lib" => \$options{'DYNAMICLIB'},
 "I=s" => \$includes,
 "h" => \$help,
 "help" => \$help,
 "clean" => \$clean
);

if($includes) {
 $options{'INCPATHS'} = "$options{'INCPATHS'}:$includes";
}

if($clean) {
 clean_files;
 exit 0;
}

if($help) {
 show_help;
 exit 0;
}
}

#
# Read local configuration
#
sub read_buildconfig() {
my $line;
my $key;
my $value;

if($builder_file) {
 open(FILE, "<$builder_file") || die("Could not open '$builder_file' file\n");
 while($line = <FILE>) {
  chop($line);

  if($line =~ /^[\ \t]*#/) {
  } else {
   ($key, $value) = split(/=/, $line);
   if($key) {
    $options{$key} = $value;
   }
  }
 }
}
close(FILE);

print "Application: $options{APPNAME} v$options{APPVERSION}\n";
print "Executable: $options{EXECUTABLE}\n" if ($options{"EXECUTABLE"});
}

#
# Search files to compile
#
sub search_files() {
find(\&search_files_find, ".");

sub search_files_find {
 my $name = $File::Find::name;
 if (!-d $name) {
  $files{$name} = $File::Find::dir;
 }
}
}

#
# Compile files
#
sub compile_files() {
my $key;

print "\n";
foreach $key (keys(%files)) {
 compile($key, $files{$key});
}
}

#
# Compile file
#
sub compile {
my ($file, $dir) = @_;

if($file =~ /\.cpp$/
|| $file =~ /\.CPP$/
|| $file =~ /\.c$/
|| $file =~ /\.C$/
|| $file =~ /\.cc$/
|| $file =~ /\.CC$/) {
 compile_cpp($file, $dir);
}
}

#
# Compile C/C++ file
#
sub compile_cpp {
my ($file, $dir) = @_;

### Output file ###
my $output = $file;
$output =~ s/\.([a-zA-Z]*)$/.o/;

### Compare dates ###
my @info_cpp = stat $file;
my @info_obj = stat $output;

if(!-f $output || $info_cpp[9] > $info_obj[9]) {
 ### Default includes ###
 my $includes = "";
 my $include_file;
 foreach $include_file (split(/:/, $options{"INCPATHS"})) {
  $includes = "$includes -I \"$include_file\"";
 }

 ### Defines ###
 my $defines = "";
 my $define;
 foreach $define (split(/:/, $options{"DEFINES"})) {
  $defines = "$defines -D \"$define\"";
 }

 ### Compiler args ###
 my $args = "$defines -c $file -o $output $includes";

 if($options{"DEBUG"}) {
  $args = "$args -g -D DEBUG";
 }

 ### Compile source file ###
 print "Compiling C++: $file > $output\n";

 my %included;
 my $recompile = 1;
 my $errors;

 while($recompile) {
  $recompile = 0;
  $errors = "";

  open(COMP, "-|", "g++ $args 2>&1");
  while(my $line = <COMP>) {
   $errors = "$errors$line";
   chop($line);

   if($line =~ /:\ (.*\.[hH])\:.No.such.file/) {
    my $include_file = search_include_file($1);
    if($include_file) {
     if(!$included{$include_file}) {
      $includes = "$includes -I \"$include_file\"";
      $included{$include_file} = 1;
      $recompile = 1;
     }
    } else {
     print "\nCannot find include file: $1\n\n";
     exit 1;
    }
   }
  }
 
  close COMP;
 }
 
 ### Print compiling errors ###
 if($errors) {
  print "$errors\n";
 }
}

### Add it to object files ###
push @cpp_objfiles, $output;
}

#
# Search directory of the include file
#
sub search_include_file {
my $include_file = shift;

my $file;
foreach $file (@incfiles) {
 if($file =~ /$include_file$/) {
  $file =~ /^(.*)$include_file$/;
  return $1;
 }
}

return "";
}

#
# Create includes cache
#
sub caching_includes {
my $dir = ".ibuilder";
my $file = "$dir/incs.cache";

if(!-f $file || $options{'CACHINGINCS'}) {
 print "\n";

 mkdir($dir, 0700) unless (-d $dir);
 unlink($file) if (-f $file);

 open(CACHE, ">$file");
 
 my $lib;
 foreach $lib (split(/:/, $options{'INCPATHS'})) {
  print "Caching include: $lib\n";
  find(\&search_incs_find, $lib);
 }
 close(CACHE);

 sub search_incs_find {
  my $name = $File::Find::name;
  my $line;

  if (!-d $name && $name =~ /\.h$/) {
   print CACHE "$name\n";
  }
 }
}
}

#
# Read includes cached
#
sub read_incscache {
my $dir = ".ibuilder";
my $file = "$dir/incs.cache";

open(INCS, "<$file");
while(my $line = <INCS>) {
 chop($line);
 push @incfiles, $line;
}
close(INCS);
}

#
# Create libraries cache
#
sub caching_libraries {
my $dir = ".ibuilder";
my $file = "$dir/libs.cache";

if(!-f $file || $options{'CACHINGLIBS'}) {
 print "\n";

 mkdir($dir, 0700) unless (-d $dir);
 unlink($file) if (-f $file);

 open(CACHE, ">$file");
 
 my $lib;
 foreach $lib (split(/:/, $options{'LIBPATHS'})) {
  print "Caching libs: $lib\n";
  find(\&search_libs_find, $lib);
 }
 close(CACHE);

 sub search_libs_find {
  my $name = $File::Find::name;
  my $line;

  if (!-d $name && $name =~ /\.a$/) {
   #print "Caching library: $name\n";
   open(LIB, "-|", "nm $name 2> /dev/null");
   while($line = <LIB>) {
    chop($line);
    if($line =~ /^[0-9a-f]+\ T\ (.*)$/) {
     print CACHE "$name: $1\n";
    }
   }
   close LIB;
  }
 }
}
}

#
# Read libraries cached
#
sub read_libscache {
my $dir = ".ibuilder";
my $file = "$dir/libs.cache";

my $line;

open(LIBS, "<$file");
while($line = <LIBS>) {
 chop($line);
 $line =~ /^(.*):\ (.*)$/;
 if($libfunctions{$2}) {
  $libfunctions{$2} = "$libfunctions{$2}:$1";
 } else {
  $libfunctions{$2} = "$1";
 }
}
close(LIBS);
}

#
# Create executable
#
sub create_executable {
caching_libraries;
read_libscache;

### Add objects file to link ###
my $file;
my $args = "";

foreach $file (@cpp_objfiles) {
 $args = "$args $file";
}

$args = "$args -o $options{EXECUTABLE}";
print "\nLinking: $options{EXECUTABLE}\n";

my $line;
my %used;
my %libpaths;
my $relinking = 0;

for $line (split(/:/, $options{"LIBS"})) {
 addlib($line);
}

open(LINK, "-|", "g++ $args 2>&1");
while($line = <LINK>) {
 chop($line);
 if($line =~ /undefined.reference.to.`(.*)'/) {
  my $function = $1;
  if($function =~ /^([^\[\(]+)::/) {
   $function = $1;
  }
  if($function =~ /\ ([^\ ]+)$/) {
   $function = $1;
  }

  my @libs = split(/:/, $libfunctions{$function});
  if(!@libs) {
   my $func;
   my %addedlib;
   foreach $func (keys(%libfunctions)) {
    if($func =~ /$function/ && !$addedlib{$libfunctions{$func}}) {
     push @libs, $libfunctions{$func};
     $addedlib{$libfunctions{$func}} = 1;
    }
   }
  }
  my $lib;

  ### Search lib for that function ###
  if(length(@libs) > 1) {
   print "Duplicate function `$function': @libs\n";
   exit 4;
  } else {
   $lib = $libs[0];
  }

  ### Add lib to link ###
  if($lib && !$used{$lib}) {
   print "Using library: $lib\n";
   addlib($lib);
  } elsif(!$lib) {
   print "Cannot find library for function $function: $line\n";
   exit 5;
  }
 }
}
close(LINK);

if($relinking) {
 `g++ $args`;
}

sub addlib {
 my $line = shift;

 $used{$line} = 1;

 my $libpath = dirname($line);
 $line = basename($line, ".a");

 $line =~ s/^lib//;
 
 $args = "$args -l$line";

 if(!$libpaths{$libpath}) {
  $libpaths{$libpath} = 1;
  $args = "$args -L$libpath";
  $relinking = 1;
 }
}
}

#
# Run the result
#
sub run {
if(!-f "./$options{EXECUTABLE}") {
 print "\nCannot find executable: ./$options{EXECUTABLE}\n";
} else {
 print "\nExecuting...\n\n";
 exec("./$options{EXECUTABLE}");
}
}

#
# Create a static lib
#
sub create_staticlib {
my $args = "";

### Add objects file to link ###
my $file;
foreach $file (@cpp_objfiles) {
 $args = "$args $file";
}

print "\nCreating static lib: lib$options{EXECUTABLE}.a\n";

`rm -f lib$options{EXECUTABLE}.a`;
`ar rcs lib$options{EXECUTABLE}.a $args`;
}

#
# Create a dynamic lib
#
sub create_dynamiclib {
my $args = "";

### Add objects file to link ###
my $file;
foreach $file (@cpp_objfiles) {
 $args = "$args $file";
}


my $lib = "lib$options{EXECUTABLE}.so";
print "\nCreating dynamic lib: $lib (soname version $options{SONAME})\n";

`rm -f $lib`;
`g++ -shared -Wl,-soname,$lib.$options{SONAME} -o $lib $args`;
}

#
# MAIN
#

autoconf;
parse_args;
read_buildconfig;

search_files;

caching_includes;
read_incscache;

compile_files;

if(!$options{'NOLINK'}) {
if(!$options{'STATICLIB'}
&& !$options{'DYNAMICLIB'}) {
 create_executable;
} else {
 if($options{'STATICLIB'}) {
  create_staticlib;
 }

 if($options{'DYNAMICLIB'}) {
  create_dynamiclib;
 }
}
}

if($options{'RUN'}) {
run;
}


josepzin

 El código fuente del Linux?? ;)  :P  :D  

TheAzazel

 Oye, sabeis la pagina donde esten documentadas las funciones de C para linux? pq me stoy volviendo loco con el maldito O_BINARY de un sencillo open()...el caso es q el resto de flag (O_CREAT, etc..) los ha pillado bien pero el O_BINARY...yo no se si es que lo han cambiado el nombre o me pego un tiro si no :S

samsaga2

Cita de: "josepzin"El código fuente del Linux?? ;)  :P  :D
El codigo fuente es en perl o sea, multisitema. Pero ya te digo yo ahora que solo te funcionara en Linux  :rolleyes:  

samsaga2

Cita de: "TheAzazel"Oye, sabeis la pagina donde esten documentadas las funciones de C para linux? pq me stoy volviendo loco con el maldito O_BINARY de un sencillo open()...el caso es q el resto de flag (O_CREAT, etc..) los ha pillado bien pero el O_BINARY...yo no se si es que lo han cambiado el nombre o me pego un tiro si no :S
Si tienes instalados los manuales de desarrollo (paquete manpages-dev en debian) tienes la ayuda del open con un:

man 2 open

PD: O_BINARY? Eso existe? el open trata los archivos como binarios puros y duros

TheAzazel

Cita de: "samsaga2"
Cita de: "TheAzazel"Oye, sabeis la pagina donde esten documentadas las funciones de C para linux? pq me stoy volviendo loco con el maldito O_BINARY de un sencillo open()...el caso es q el resto de flag (O_CREAT, etc..) los ha pillado bien pero el O_BINARY...yo no se si es que lo han cambiado el nombre o me pego un tiro si no :S
Si tienes instalados los manuales de desarrollo (paquete manpages-dev en debian) tienes la ayuda del open con un:

man 2 open

PD: O_BINARY? Eso existe? el open trata los archivos como binarios puros y duros
Pues eso me temo, mi temor era que los pudiera abrir como texto.... pero indagando e indagando... (aunq no he visto nada especifico) creo que el open los abre como binarios (tuve q hacer un ejemplo a ver q pasaba jiji).
Voy a ver eso de los manuales pq es un pesti;o cada vez que quiero ver tal o cual funcion o en que header esta... muchas gracias!! y por cierto, gracias a tu script he conseguido entender un poco mas como va todo esto. Sobre las funcionalidades extras...luego vi que el icompile tambien lo hace (librerias estaticas, dinamicas y esas cosillas) aunq...tras dedicarle un tiempo al makefile, para lo que lo quiero q es algo normal ya me vale. Lo bueno, que leyendo las fuentes de tu script, del icompile y con un manual por ahi... he adkirido conocimiento jejeje, como suena eh? :) pos otra vez, gracias por echarme un cable!






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.